import 'dart:async';
import 'package:blocks_blkk/components/return_button.dart';
import 'package:webview_flutter_plus/webview_flutter_plus.dart';

import 'package:xml/xml.dart' as xml;
import 'package:yundongjia_ble/yundongjia_ble.dart';

import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'device_data_context.dart';
import 'entity/program_entity.dart';
import 'function_page.dart';
import 'mixins/action_mixin.dart';

class ProgramPage extends FunctionPage {
  //final String filename;
  final ProgramEntity programEntity;
  ProgramPage({super.key, required this.programEntity});

  @override
  ProgramPageState createState() =>
      ProgramPageState(programEntity: programEntity);
}

class ProgramPageState extends FunctionPageState with ActionMixin {
  ProgramEntity? programEntity;
  bool _playing = false;
  bool _showSaveDialoge = false;
  String? text = '';
  String? originName = '';
  // String htmlName;
  late WebViewControllerPlus webViewControllerComp;
  xml.XmlNode? _currentNode;
  xml.XmlDocument? _document;
  bool get playing => _playing;

  @override
  void initState() {
    super.initState();
    String fiepath = 'assets/scratch/$htmlPath';
    debugPrint('初始化文件 $fiepath');
    webViewControllerComp = WebViewControllerPlus()
      ..loadFlutterAssetServer(fiepath)
      ..setJavaScriptMode(JavaScriptMode.unrestricted)
      ..setBackgroundColor(const Color(0x00000000))
      ..setNavigationDelegate(
        NavigationDelegate(
          onPageFinished: (url) {
            webViewControllerComp.getWebViewHeight().then((value) {
              // var height = int.parse(value.toString()).toDouble();
              // if (height != _height) {
              //   if (kDebugMode) {
              //     print("Height is: $value");
              //   }
              //   setState(() {
              //     _height = height;
              //   });
              // }
            });
          },
        ),
      );
  }

  @override
  void dispose() {
    super.dispose();
    actionStop();

    _playing = false;
  }

  String? get programeType {
    return programEntity?.name;
  }

  String get htmlPath {
    //return htmlName;
    return "index_2.html";
  }

  set playing(bool v) {
    _playing = v;
  }

  ProgramPageState({this.programEntity});

  void loadRoot() {
    // print('_loadRoot 调用');
    String? str = programEntity?.txt;
    if (str != null && str.isNotEmpty) {
      webViewControllerComp.runJavaScript('fromXml(\'$str\')');
    }
    originName = programEntity?.name;
  }

  void _saveRoot() {
    webViewControllerComp.runJavaScript('toXml("workspacexml")').then((param) {
      String str = param as String;
      if (str.isNotEmpty) {
        str = str.replaceAll("\n", "");
        str = str.replaceAll("\\n", "");
        str = str.replaceAll('\\u003C', '<');
        str = str.replaceAll('\\', '');
        if (str.startsWith("\"")) {
          str = str.substring(1);
        }
        if (str.endsWith("\"")) {
          str = str.substring(0, str.length - 1);
        }
        programEntity?.txt = str;
      }
    });
    setState(() {
      text = programEntity?.name;
      _showSaveDialoge = true;
    });
  }

  @override
  Widget build(BuildContext context) {
    //print('remote build');
    //platform.invokeMethod('setControl');
    return Container(
      child: Container(
        child: Stack(children: <Widget>[
          //webview
          positionedWebviewController(),

          //_mainWidget(),
          //_bottomWidget(),
          controlBtn(),
          //_breakTips(),

          //键盘
          //_keyWidget(),

          saveDialogContent(),

          //返回按钮 在最上层
          ReturnButton(callback: func),
          bluetootnBtn(shape: BoxShape.rectangle),
          //playBtn(),
        ]),
      ),
    );
  }

  ProgramEntity? func() {
    return programEntity;
  }

  Widget saveDialogContent() {
    if (_showSaveDialoge) {
      return Positioned(
        left: ScreenUtil().setWidth(368),
        top: ScreenUtil().setWidth(40),
        width: ScreenUtil().setWidth(600),
        height: ScreenUtil().setHeight(200),
        child: Container(
          decoration: BoxDecoration(
            borderRadius: BorderRadius.circular(5.0),
            color: Colors.orange[300],
          ),
          child: Stack(
            children: <Widget>[
              Positioned(
                left: ScreenUtil().setWidth(100),
                bottom: ScreenUtil().setWidth(50),
                right: ScreenUtil().setWidth(100),
                height: ScreenUtil().setHeight(80),
                child: Container(
                  color: Colors.white,
                  child: Scaffold(
                    resizeToAvoidBottomInset: false,
                    body: TextField(
                      controller: TextEditingController(text: text),
                      style: DefaultTextStyle.of(context).style.apply(
                          backgroundColor: Colors.white,
                          color: Colors.black,
                          fontSizeFactor: 0.4,
                          decoration: TextDecoration.none),
                      onChanged: (v) {
                        text = v;
                      },
                      onSubmitted: (v) {
                        FocusScope.of(context).requestFocus(FocusNode());
                        // SystemChrome.setEnabledSystemUIOverlays([]);
                        setState(() {
                          _showSaveDialoge = false;
                          programEntity?.name = text;
                        });
                      },
                    ),
                  ),
                ),
              ),
            ],
          ),
        ),
      );
    } else {
      return Container();
    }
  }

  //控制按钮
  Widget controlBtn() {
    return Positioned(
      top: ScreenUtil().setHeight(30),
      right: 20,
      width: ScreenUtil().setWidth(200),
      height: ScreenUtil().setWidth(85),
      child: Row(
        children: <Widget>[
          //启动按钮
          GestureDetector(
            onTap: playing ? stopClick : playClick,
            child: Image(
              image: AssetImage(playing
                  ? 'assets/control_pause.png'
                  : 'assets/icon_pro_start.png'),
            ),
          ),

          Expanded(
            child: Container(),
          ),
          //保存按钮
          GestureDetector(
            onTap: _saveRoot,
            child: const Image(
              image: AssetImage('assets/icon_save.png'),
            ),
          ),
        ],
      ),
    );
  }

  //保存
  void _saveClick() async {
    debugPrint('点击保存按钮');
    // setState(() {
    //   _currentId = '';
    //   _saveRoot();
    // });
    // webViewControllerComp
    //     .evaluateJavascript('toXml("workspacexml")')
    //     .then((str) {
    //   //print('return from webview valeue = $str');
    // });

    setState(() {
      text = '';
      _showSaveDialoge = true;
    });
  }

  @override
  IconData getPlayIcon() {
    return playing ? Icons.stop : Icons.play_arrow;
  }

  Future<void> playClick() async {
    setState(() {
      playing = true;
    });

    webViewControllerComp
        .runJavaScriptReturningResult('toXml("workspacexml")')
        .then((param) {
      //print('str= $str');
      String str = param as String;
      if (str.isNotEmpty) {
        str = str.replaceAll("\n", "");
        str = str.replaceAll("\\n", "");
        str = str.replaceAll('\\u003C', '<');
        str = str.replaceAll('\\', '');
        if (str.startsWith("\"")) {
          str = str.substring(1);
        }
        if (str.endsWith("\"")) {
          str = str.substring(0, str.length - 1);
        }
        _document = xml.XmlDocument.parse(str);
        _currentNode = getRootNodeFromDocument();
        playClickAction();
      }
    });
    //webViewControllerComp.evaluateJavascript('toXml()');
  }

  //播放
  Future<void> playClickAction() async {
    if (!playing) {
      actionStop();
      return;
    }

    List? list = getNextAction();
    if (list == null || list.isEmpty) {
      actionStop();
      setState(() {
        playing = false;
      });
      return;
    }

    String currentname = list[0];
    debugPrint('currentname $currentname $list');
    switch (currentname) {
      case 'motor_stop':
        motorStop(list);
        break;
      case 'two_motor_stop':
        twoMotorStop(list);
        break;
      case 'motor_run':
        motorRun(list);
        break;
      case 'motor_run_time':
        motorRunTime(list);
        break;
      case 'two_motor_run':
        twoMotorRun(list);
        break;
      case 'two_motor_run_time':
        twoMotorRunTime(list);
        break;
      case 'two_motor_run_s':
        twoMotorRuns(list);
        break;
      case 'two_motor_run_time_s':
        twoMotorRunTimes(list);
        break;
      default:
    }

    await Future.delayed(const Duration(milliseconds: 500), () {
      playClickAction();
    });
  }

  //停止
  void stopClick() {
    //print('点击停止按钮');

    setState(() {
      playing = false;
    });
  }

  //Future<void> actionLoop4(String value) async {}

  //////////////////////////////
  /////
  ///

  //WebView HTML页面控件
  Widget positionedWebviewController() {
    return Positioned(
        left: 0.0,
        right: 0.0,
        top: 0.0,
        bottom: 0.0,
        child: webviewController());
  }

  Widget webviewController() {
    return WebViewWidget(
      //initialUrl: fiepath,
      // javascriptMode: JavascriptMode.unrestricted,
      // onWebViewCreated: (WebViewController webViewController) {
      //   webViewControllerComp = webViewController;
      //   webViewController.loadUrl(fiepath);
      // },
      // // javascriptChannels: <JavascriptChannel>[
      // //   toasterJavascriptChannel(context),
      // // ].toSet(),
      // // navigationDelegate: (NavigationRequest request) {
      // //   //print('allowing navigation to $request');
      // //   return NavigationDecision.navigate;
      // // },
      // onPageFinished: (String url) {
      //   // print('Page finished loading: $url');
      //   loadRoot();
      // },
      controller: webViewControllerComp,
    );
  }

  xml.XmlNode? getRootNodeFromDocument() {
    //print('getRootNodeFromDocument');
    xml.XmlNode? result;
    xml.XmlElement? element = _document?.getElement('xml');

    result = _getFromChild(element);
    return result;
  }

  xml.XmlNode? _getFromChild(xml.XmlNode? node) {
    xml.XmlNode? result;
    result = node?.getElement('block');

    return result;
  }

  // 获得下一个命令
  List? getNextAction() {
    if (!playing) {
      actionStop();
      return null;
    }
    List? nodeDats;
    //当前节点完成，继续下一个Block 否则继续执行
    // List list = getNextAction1();
    if (_isFinished(_currentNode)) {
      //print('nextNode $_currentNode');
      //actionStop();
      xml.XmlNode? nextNode = _getNextBlock(_currentNode);
      if (nextNode != null) {
        String times = _getTimesValue(nextNode, initial: true);
        _setFinished(nextNode, int.parse(times));
        _currentNode = nextNode;
      } else {
        xml.XmlNode? parentUnfinishNode = _loopGetUnfinisheParent(_currentNode);
        if (parentUnfinishNode != null) {
          _currentNode = parentUnfinishNode;
        } else {
          //print('Program1 父级退出');
          return null;
        }
      }
    }

    String? type = _currentNode?.getAttribute('type');
    nodeDats = getNextActionData(_currentNode);
    //print('父级 $type');
    //general type
    int times = _getFinishValue(_currentNode);
    debugPrint('节点名称=  $type tiems = $times');
    if (times > 0) {
      times = times - 1;
      _setFinished(_currentNode, times);
    } else {
      times = times - 1;
      _setFinished(_currentNode, 0);
    }

    //如果是起始点 寻找下个节点
    if (type == 'event_whenflagclicked') {
      xml.XmlNode? nextNode = _getNextBlock(_currentNode);
      if (nextNode != null) {
        debugPrint('set finish');
        String times = _getTimesValue(nextNode, initial: true);
        _setFinished(nextNode, int.parse(times));
        _currentNode = nextNode;
        return getNextAction();
      }
    }

    // if (type == 'control_stop') {
    //   //return nodeDats;
    //   return [type]; ////return _curretNode.action
    // }

    //如果是循环节点
    if (type == 'control_repeat_forever' || type == 'control_repeat') {
      if (times > -1) {
        xml.XmlNode? nextNode = _getStatementBlock(_currentNode);
        if (nextNode != null) {
          String times = _getTimesValue(nextNode, initial: true);
          _setFinished(nextNode, int.parse(times));
          _currentNode = nextNode;
        }
      } else {
        xml.XmlNode? nextNode = _getNextBlock(_currentNode);
        if (nextNode != null) {
          String times = _getTimesValue(nextNode, initial: true);
          _setFinished(nextNode, int.parse(times));
          _currentNode = nextNode;
        }
      }
      //print('Program 2 父级退出');
      return getNextAction();
    }

    //print('Program 3 父级退出');
    return nodeDats;
  }

  int _getFinishValue(xml.XmlNode? node) {
    String times = _getTimesValue(node);
    int count = int.parse(times);
    return count;
  }

  //是否完成
  bool _isFinished(xml.XmlNode? node) {
    String? times = node?.getAttribute('finish');
    if (times == null) {
      return true;
    } else {
      return int.parse(times) < 1;
    }
  }

  //设置完成
  void _setFinished(xml.XmlNode? node, int finish) {
    if (node is xml.XmlElement) {
      node.setAttribute('finish', finish.toString());
      // print(
      //     '_setFinished ${node.name} ${node.getAttribute('type')} finish=$finish');
    }
  }

  //获得循环次数
  String _getTimesValue(xml.XmlNode? node, {bool initial = false}) {
    List? list = getNextActionData(node);

    //print('list === $list');

    if (!initial) {
      String? times = node?.getAttribute('finish');
      if (times != null) {
        return times;
      }
    }

    if (list == null) {
      return '0';
    }
    if (list.isEmpty) {
      return '0';
    }

    if (list[0] == 'control_repeat_forever') {
      return (1 << 31).toString();
    }
    if (list[0] == 'event_whenflagclicked') {
      return '1';
    }
    if (list[0] == 'control_repeat') {
      Map m = list[1];
      return m['TIME'];
    }

    for (int i = 1; i < list.length; i++) {
      Map m = list[i];
      String? s = m['TIME_INPUT'];
      if (s != null) {
        return '${(int.parse(s) * 2)}';
      }
    }
    return '1';

    // xml.XmlElement element = node.getElement('value');
    // if (element == null) {
    //   return '0';
    // }
    // Iterable<xml.XmlElement> fields = element.findAllElements('field');
    // if (fields.isEmpty) {
    //   return '0';
    // }
    // xml.XmlElement field = fields.first;
    // xml.XmlNode text = field.firstChild;
    // if (text == null) {
    //   return '0';
    // }

    // String nodetimes = text.toString();
    // print(' _getTimesValue $str $nodetimes');
    // return nodetimes;

    //return str;
  }

  //父级未完成的节点
  xml.XmlNode? _loopGetUnfinisheParent(final xml.XmlNode? node) {
    //xml.XmlNode result;
    if (node == null) {
      return null;
    }
    xml.XmlNode? curNode = node.parent;
    if (curNode == null) {
      return null;
    }

    if (curNode.parent != null) {
      //print(curNode.toXmlString());
      if (curNode is xml.XmlElement && curNode.name.toString() == 'statement') {
        // String? type = curNode.parent?.getAttribute('type');
        // if (type != null && type == 'control_forever') {
        return curNode.parent;
        // }
      }

      return _loopGetUnfinisheParent(curNode.parent);
    }
    return null;
  }

  String getValueData(xml.XmlNode? node, String tagname) {
    if (node == null) {
      return '';
    }
    if (node is xml.XmlElement) {
      for (xml.XmlNode n in node.descendants) {
        if (n is xml.XmlElement) if (n.name.toString() == tagname) {
          return n.children[0].text;
        }
      }
    }
    return '';
  }

  List? getNextActionData(xml.XmlNode? node) {
    List list = [];
    if (node is xml.XmlElement) {
      //print('node.name =  ${node.name}');
      if (node.name.toString() == 'block') {
        String? typeName = node.getAttribute('type');
        //print('typeName =  $typeName');
        list.add(typeName);
      }
      for (var n in node.children) {
        if (n is xml.XmlElement) {
          switch (n.name.toString()) {
            case 'field':
              {
                String? fieldName = n.getAttribute('name');
                String fieldText = n.children[0].text;
                list.add({fieldName: fieldText.trim()});
              }
              break;
            case 'value':
              {
                String? fieldName = n.getAttribute('name');
                String fieldText = getValueData(n.firstElementChild, 'field');
                list.add({fieldName: fieldText.trim()});
              }
              break;
          }
        }
      }
      return list;
    }
  }

  xml.XmlNode? _getNextBlock(xml.XmlNode? node) {
    return getBlocks(node, 'next');
  }

  xml.XmlNode? _getStatementBlock(xml.XmlNode? node) {
    return getBlocks(node, 'statement');
  }

  xml.XmlNode? getBlocks(xml.XmlNode? node, String nodetype) {
    xml.XmlElement? next = node?.getElement(nodetype);
    if (next == null) {
      return null;
    }
    xml.XmlElement? result = next.getElement('block');
    return result;
  }

  //停止
  void actionStop() {
    YundongjiaBle.instance
        .sendAdvertiseCommand(DeviceDataContext.instance.devcie.actionStop());
  }

  //前进
  void actionForward({bool reverse = false}) {
    YundongjiaBle.instance.sendAdvertiseCommand(
        DeviceDataContext.instance.devcie.actionForward(reverse: reverse));
  }

  //后退
  void actionBackward({bool reverse = false}) {
    YundongjiaBle.instance.sendAdvertiseCommand(
        DeviceDataContext.instance.devcie.actionBackward(reverse: reverse));
  }

  //左转
  void actionLeft({bool reverse = false}) {
    YundongjiaBle.instance.sendAdvertiseCommand(
        DeviceDataContext.instance.devcie.actionLeft(reverse: reverse));
  }

  //右转
  void actionRight({bool reverse = false}) {
    YundongjiaBle.instance.sendAdvertiseCommand(
        DeviceDataContext.instance.devcie.actionRight(reverse: reverse));
  }

  //左转前进
  void actionForwardLeft(
      {bool verticalReverse = false, bool horizontalReverse = false}) {
    YundongjiaBle.instance.sendAdvertiseCommand(
        DeviceDataContext.instance.devcie.actionForwardLeft(
            verticalReverse: verticalReverse,
            horizontalReverse: horizontalReverse));
  }

  //右转前进
  void actionForwardRight(
      {bool verticalReverse = false, bool horizontalReverse = false}) {
    YundongjiaBle.instance.sendAdvertiseCommand(
        DeviceDataContext.instance.devcie.actionForwardRight(
            verticalReverse: verticalReverse,
            horizontalReverse: horizontalReverse));
  }

  //左转后退
  void actionBackwardLeft(
      {bool verticalReverse = false, bool horizontalReverse = false}) {
    YundongjiaBle.instance.sendAdvertiseCommand(
        DeviceDataContext.instance.devcie.actionBackwardLeft(
            verticalReverse: verticalReverse,
            horizontalReverse: horizontalReverse));
  }

  //右转后退
  void actionBackwardRight(
      {bool verticalReverse = false, bool horizontalReverse = false}) {
    YundongjiaBle.instance.sendAdvertiseCommand(
        DeviceDataContext.instance.devcie.actionBackwardRight(
            verticalReverse: verticalReverse,
            horizontalReverse: horizontalReverse));
  }

  String? blockAttribute(List list, String key) {
    Map map = list
        .firstWhere((element) => element is Map && element.keys.contains(key));
    if (map != null) {
      String str = map[key];
      return str;
    }
    return null;
  }

  int getMotorAIndex() {
    return 4;
  }

  int getMotorBIndex() {
    return 5;
  }

  //单马达停止
  void motorStop(List list) {
    String? str = blockAttribute(list, 'INTERFACE_OPTION');
    if (str != null) {
      if (str == '1') {
        YundongjiaBle.instance.sendAdvertiseCommand(DeviceDataContext
            .instance.devcie
            .getDataAt(getMotorAIndex(), 0x80));
      } else if (str == '2') {
        YundongjiaBle.instance.sendAdvertiseCommand(DeviceDataContext
            .instance.devcie
            .getDataAt(getMotorBIndex(), 0x80));
      }
    }
  }

  //双马达停止
  void twoMotorStop(List list) {
    DeviceDataContext.instance.devcie.getDataAt(getMotorAIndex(), 0x80);
    YundongjiaBle.instance.sendAdvertiseCommand(
        DeviceDataContext.instance.devcie.getDataAt(getMotorBIndex(), 0x80));
  }

  //单马达运行
  void motorRun(List list) {
    String? iface = blockAttribute(list, 'INTERFACE_OPTION');
    String? speed = blockAttribute(list, 'SPEED_OPTION');
    String? direct = blockAttribute(list, 'DIRECTION_OPTION');
    int materIndex = iface == '1' ? getMotorAIndex() : getMotorBIndex();
    int speedIndex = (int.parse(speed ?? '0') / 100.0 * 0x7F).toInt();
    int directIndex = direct == '1' ? -1 : 1;
    speedIndex = 0x80 + directIndex * speedIndex;
    YundongjiaBle.instance.sendAdvertiseCommand(DeviceDataContext
        .instance.devcie
        .getDataAt(materIndex, speedIndex + directIndex));
  }

  //单马达运行带时间
  void motorRunTime(List list) {
    motorRun(list);
  }

  //双马达运行
  void twoMotorRun(List list) {
    String? speed = blockAttribute(list, 'SPEED_OPTION');
    String? direct = blockAttribute(list, 'DIRECTION_OPTION');

    int speedIndex = (int.parse(speed ?? '0') / 100.0 * 0x7F).toInt();
    int directIndex = direct == '1' ? -1 : 1;
    speedIndex = 0x80 + directIndex * speedIndex;

    DeviceDataContext.instance.devcie.getDataAt(getMotorAIndex(), speedIndex);
    YundongjiaBle.instance.sendAdvertiseCommand(DeviceDataContext
        .instance.devcie
        .getDataAt(getMotorBIndex(), speedIndex));
  }

  //双马达运行带时间
  void twoMotorRunTime(List list) {
    twoMotorRun(list);
  }

  void twoMotorRuns(List list) {
    // print('twoMotorRuns ${list}');
    String? iface1 = blockAttribute(list, 'INTERFACE_OPTION1');
    String? direct1 = blockAttribute(list, 'DIRECTION_OPTION1');
    String? iface2 = blockAttribute(list, 'INTERFACE_OPTION2');
    String? direct2 = blockAttribute(list, 'DIRECTION_OPTION2');
    String? speed = blockAttribute(list, 'SPEED_OPTION');
    int materIndex = iface1 == '1' ? getMotorAIndex() : getMotorBIndex();
    int directIndex = direct1 == '1' ? -1 : 1;
    int speedIndex = (int.parse(speed ?? '0') / 100.0 * 0x7F).toInt();
    speedIndex = 0x80 + directIndex * speedIndex;

    DeviceDataContext.instance.devcie.getDataAt(materIndex, speedIndex);
    directIndex = direct2 == '1' ? -1 : 1;
    materIndex = iface2 == '1' ? getMotorAIndex() : getMotorBIndex();
    speedIndex = (int.parse(speed ?? '0') / 100.0 * 0x7F).toInt();
    speedIndex = 0x80 + directIndex * speedIndex;

    YundongjiaBle.instance.sendAdvertiseCommand(
        DeviceDataContext.instance.devcie.getDataAt(materIndex, speedIndex));
  }

  void twoMotorRunTimes(List list) {
    twoMotorRuns(list);
  }
}
